package servidorapjava.modelo;

import apjava.basico.ClienteModel;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import servidorapjava.*;
import servidorapjava.dados.ConstanteInformacao;
import servidorapjava.dados.GerenciadorMensagem;

public class PrincipalServidor implements Runnable{
    
    private static ArrayList<ClienteModel> clientes = new ArrayList<ClienteModel>();;
    private int portaPadrao = 5000;
    private static int portaAtual = 5000;
    private ServerSocket conexaoPadrao;
    private static String ipServidor;
    
    private static PrincipalServidor instance;
    
    private PrincipalServidor() {
        //Pegando o IP do servidor(Local)
        try {
            ipServidor = InetAddress.getLocalHost().getHostAddress();
            System.out.println("IP do servidor: " + ipServidor);
        } catch (UnknownHostException ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }
    
    public static PrincipalServidor getInstance() {
        if(instance == null) {
            instance = new PrincipalServidor();
        }
        return instance;
    }
    
    public void run() {
        try {
            conexaoPadrao = new ServerSocket(portaPadrao);
            System.out.println("Servidor preparado!");
        } catch (IOException ex) {
            System.out.println("Erro ao iniciar o servidor.\nDica: Verifique se a porta esta em uso");
            ex.printStackTrace();
            return;
        }
        while (true) {
            System.out.println("");
            System.out.println("Servidor aguardando novas conexoes...");
            Socket novaConexao = null;
            try {
                novaConexao = conexaoPadrao.accept();
                
                System.out.println("Pedido de conexao aceito: " + novaConexao.getInetAddress().getHostAddress() + ":"+ novaConexao.getPort());
                
                //Criando cliente
                ClienteModel cliente = new ClienteModel();
                cliente.setConexaoCliente(novaConexao);
                cliente.setIp(novaConexao.getInetAddress().getHostAddress());
                cliente.setPortaEnvioVideo(getProximaPorta());
                
                if(this.getClientes().contains(cliente)) {
                    System.out.println("Cliente ja conectado!");
                    continue;
                }
                System.out.println("Adicionando o Cliente a Lista");
                this.getClientes().add(cliente);
                cliente.setLogado(true);
                enviaListaAtualParaClientes();
                
                System.out.println("Criando uma nova Thread para tratar as requisicoes desde cliente");
                new Thread(new TratadorConexaoServidor(cliente)).start();
//                threadsEscuta.put(cliente.toString(), t);                
            } catch (IOException ex) {
                System.out.println("Nao pode aceitar o Cliente");
                ex.printStackTrace();
                continue;
            }
            
        }
    }

    public void removerCliente(ClienteModel cliente) {
        //Removendo o cliente da listagem
        clientes.remove( cliente );
        
        //Removendo a thread que escuta o cliente
//        Thread t = threadsEscuta.get(cliente.toString());
//        t.interrupt();
    }
    
    public void enviaListaAtualParaClientes() {
        // Enviando a lista de clientes aos clientes
        System.out.println(">>> Enviando lista para clientes:" + this.getClientes());
        for (ClienteModel elem : clientes) {
            System.out.println(" ::>Para cliente:" + elem);
            GerenciadorMensagem.enviaMensagem(ConstanteInformacao.LISTA_CLIENTES, this.getClientes(), elem);
        }
        System.out.println("<<< Enviando lista para clientes");
    }
    
    private int getProximaPorta() {
        portaAtual+=2;
        return portaAtual;
    }
    
    public synchronized ArrayList<ClienteModel> getClientes() {
        return clientes;
    }
    
    public String getIpServidor() {
        return ipServidor;
    }
}
